using System;
using System.Threading;

namespace MT5Trade.Models
{
    /// <summary>
    /// 熔断器实现
    /// 用于防止系统雪崩效应，在连续失败后自动断开服务调用
    /// </summary>
    public class CircuitBreaker
    {
        #region 熔断器状态枚举

        /// <summary>
        /// 熔断器状态
        /// </summary>
        public enum CircuitBreakerState
        {
            /// <summary>
            /// 关闭状态 - 正常运行，允许所有请求通过
            /// </summary>
            Closed,
            
            /// <summary>
            /// 开启状态 - 熔断激活，拒绝所有请求
            /// </summary>
            Open,
            
            /// <summary>
            /// 半开状态 - 测试恢复，允许有限的请求通过
            /// </summary>
            HalfOpen
        }

        #endregion

        #region 常量定义

        // 默认配置
        public const int DEFAULT_FAILURE_THRESHOLD = 5;        // 默认失败阈值
        public const int DEFAULT_SUCCESS_THRESHOLD = 2;        // 半开状态成功阈值
        public const int DEFAULT_TIMEOUT_SECONDS = 30;         // 默认超时时间（秒）
        public const int DEFAULT_HALF_OPEN_MAX_ATTEMPTS = 3;   // 半开状态最大尝试次数

        #endregion

        #region 私有字段

        private readonly object _lockObj = new object();
        private CircuitBreakerState _state;
        private int _failureCount;
        private int _successCount;
        private DateTime _lastFailureTime;
        private DateTime _stateChangedTime;
        private readonly int _failureThreshold;
        private readonly int _successThreshold;
        private readonly TimeSpan _openTimeout;
        private readonly int _halfOpenMaxAttempts;
        private int _halfOpenAttempts;

        #endregion

        #region 公共属性

        /// <summary>
        /// 当前熔断器状态
        /// </summary>
        public CircuitBreakerState State
        {
            get
            {
                lock (_lockObj)
                {
                    return _state;
                }
            }
        }

        /// <summary>
        /// 当前失败计数
        /// </summary>
        public int FailureCount
        {
            get
            {
                lock (_lockObj)
                {
                    return _failureCount;
                }
            }
        }

        /// <summary>
        /// 熔断器是否开启
        /// </summary>
        public bool IsOpen
        {
            get
            {
                lock (_lockObj)
                {
                    UpdateState();
                    return _state == CircuitBreakerState.Open;
                }
            }
        }

        /// <summary>
        /// 熔断器是否允许请求通过
        /// </summary>
        public bool AllowRequest
        {
            get
            {
                lock (_lockObj)
                {
                    UpdateState();
                    
                    switch (_state)
                    {
                        case CircuitBreakerState.Closed:
                            return true;
                            
                        case CircuitBreakerState.Open:
                            return false;
                            
                        case CircuitBreakerState.HalfOpen:
                            // 半开状态下限制请求数量
                            if (_halfOpenAttempts < _halfOpenMaxAttempts)
                            {
                                _halfOpenAttempts++;
                                return true;
                            }
                            return false;
                            
                        default:
                            return false;
                    }
                }
            }
        }

        #endregion

        #region 构造函数

        /// <summary>
        /// 初始化熔断器
        /// </summary>
        /// <param name="failureThreshold">触发熔断的失败次数阈值</param>
        /// <param name="successThreshold">半开状态恢复到关闭状态所需的成功次数</param>
        /// <param name="openTimeoutSeconds">开启状态持续时间（秒）</param>
        /// <param name="halfOpenMaxAttempts">半开状态最大尝试次数</param>
        public CircuitBreaker(
            int failureThreshold = DEFAULT_FAILURE_THRESHOLD,
            int successThreshold = DEFAULT_SUCCESS_THRESHOLD,
            int openTimeoutSeconds = DEFAULT_TIMEOUT_SECONDS,
            int halfOpenMaxAttempts = DEFAULT_HALF_OPEN_MAX_ATTEMPTS)
        {
            _failureThreshold = Math.Max(1, failureThreshold);
            _successThreshold = Math.Max(1, successThreshold);
            _openTimeout = TimeSpan.FromSeconds(Math.Max(1, openTimeoutSeconds));
            _halfOpenMaxAttempts = Math.Max(1, halfOpenMaxAttempts);

            _state = CircuitBreakerState.Closed;
            _failureCount = 0;
            _successCount = 0;
            _halfOpenAttempts = 0;
            _stateChangedTime = DateTime.UtcNow;
        }

        /// <summary>
        /// 兼容性构造函数：支持TimeSpan参数
        /// </summary>
        /// <param name="failureThreshold">触发熔断的失败次数阈值</param>
        /// <param name="resetTimeout">重置超时时间</param>
        /// <param name="halfOpenMaxAttempts">半开状态最大尝试次数</param>
        public CircuitBreaker(
            int failureThreshold,
            TimeSpan resetTimeout,
            int halfOpenMaxAttempts)
            : this(failureThreshold, DEFAULT_SUCCESS_THRESHOLD, (int)resetTimeout.TotalSeconds, halfOpenMaxAttempts)
        {
        }

        #endregion

        #region 核心方法

        /// <summary>
        /// 记录成功
        /// </summary>
        public void RecordSuccess()
        {
            lock (_lockObj)
            {
                UpdateState();
                
                switch (_state)
                {
                    case CircuitBreakerState.Closed:
                        // 关闭状态下，重置失败计数
                        _failureCount = 0;
                        break;
                        
                    case CircuitBreakerState.HalfOpen:
                        // 半开状态下，增加成功计数
                        _successCount++;
                        
                        // 如果达到成功阈值，转换到关闭状态
                        if (_successCount >= _successThreshold)
                        {
                            ChangeState(CircuitBreakerState.Closed);
                            _failureCount = 0;
                            _successCount = 0;
                            _halfOpenAttempts = 0;
                        }
                        break;
                        
                    case CircuitBreakerState.Open:
                        // 开启状态不应该有成功记录（理论上不应该到达这里）
                        break;
                }
            }
        }

        /// <summary>
        /// 记录失败
        /// </summary>
        public void RecordFailure()
        {
            lock (_lockObj)
            {
                UpdateState();
                
                _lastFailureTime = DateTime.UtcNow;
                
                switch (_state)
                {
                    case CircuitBreakerState.Closed:
                        // 关闭状态下，增加失败计数
                        _failureCount++;
                        
                        // 如果达到失败阈值，转换到开启状态
                        if (_failureCount >= _failureThreshold)
                        {
                            ChangeState(CircuitBreakerState.Open);
                        }
                        break;
                        
                    case CircuitBreakerState.HalfOpen:
                        // 半开状态下任何失败立即转换到开启状态
                        ChangeState(CircuitBreakerState.Open);
                        _successCount = 0;
                        _halfOpenAttempts = 0;
                        break;
                        
                    case CircuitBreakerState.Open:
                        // 开启状态下继续记录失败（用于统计）
                        _failureCount++;
                        break;
                }
            }
        }

        /// <summary>
        /// 重置熔断器
        /// </summary>
        public void Reset()
        {
            lock (_lockObj)
            {
                ChangeState(CircuitBreakerState.Closed);
                _failureCount = 0;
                _successCount = 0;
                _halfOpenAttempts = 0;
                _lastFailureTime = DateTime.MinValue;
            }
        }

        /// <summary>
        /// 执行带熔断保护的操作
        /// </summary>
        /// <typeparam name="T">返回类型</typeparam>
        /// <param name="operation">要执行的操作</param>
        /// <returns>操作结果</returns>
        public T Execute<T>(Func<T> operation)
        {
            if (!AllowRequest)
            {
                throw new CircuitBreakerOpenException($"熔断器开启，拒绝请求。状态: {State}, 失败次数: {FailureCount}");
            }
            
            try
            {
                var result = operation();
                RecordSuccess();
                return result;
            }
            catch (Exception ex)
            {
                RecordFailure();
                throw new CircuitBreakerExecutionException("操作执行失败，熔断器已记录", ex);
            }
        }

        /// <summary>
        /// 尝试执行带熔断保护的操作
        /// </summary>
        public bool TryExecute<T>(Func<T> operation, out T result, out Exception error)
        {
            result = default(T);
            error = null;
            
            if (!AllowRequest)
            {
                error = new CircuitBreakerOpenException($"熔断器开启，拒绝请求。状态: {State}");
                return false;
            }
            
            try
            {
                result = operation();
                RecordSuccess();
                return true;
            }
            catch (Exception ex)
            {
                RecordFailure();
                error = ex;
                return false;
            }
        }

        /// <summary>
        /// 执行带熔断保护的异步操作
        /// </summary>
        /// <typeparam name="T">返回值类型</typeparam>
        /// <param name="operation">要执行的异步操作</param>
        /// <returns>操作结果</returns>
        public async System.Threading.Tasks.Task<T> ExecuteWithCircuitBreakerAsync<T>(
            Func<System.Threading.Tasks.Task<T>> operation)
        {
            if (!AllowRequest)
            {
                throw new CircuitBreakerOpenException(
                    $"熔断器开启，拒绝请求。状态: {State}, 失败次数: {FailureCount}");
            }

            try
            {
                var result = await operation();
                RecordSuccess();
                return result;
            }
            catch (Exception ex)
            {
                RecordFailure();
                throw new CircuitBreakerExecutionException("操作执行失败，熔断器已记录", ex);
            }
        }

        /// <summary>
        /// 兼容性方法：执行异步操作
        /// </summary>
        /// <typeparam name="T">返回类型</typeparam>
        /// <param name="operation">要执行的异步操作</param>
        /// <returns>操作结果</returns>
        public async System.Threading.Tasks.Task<T> ExecuteAsync<T>(Func<System.Threading.Tasks.Task<T>> operation)
        {
            return await ExecuteWithCircuitBreakerAsync(operation);
        }

        #endregion

        #region 私有方法

        /// <summary>
        /// 更新熔断器状态
        /// </summary>
        private void UpdateState()
        {
            if (_state == CircuitBreakerState.Open)
            {
                // 检查是否应该转换到半开状态
                var timeSinceOpen = DateTime.UtcNow - _stateChangedTime;
                if (timeSinceOpen >= _openTimeout)
                {
                    ChangeState(CircuitBreakerState.HalfOpen);
                    _halfOpenAttempts = 0;
                }
            }
        }

        /// <summary>
        /// 改变熔断器状态
        /// </summary>
        private void ChangeState(CircuitBreakerState newState)
        {
            if (_state != newState)
            {
                var oldState = _state;
                _state = newState;
                _stateChangedTime = DateTime.UtcNow;
                
                // 触发状态变更事件
                OnStateChanged(oldState, newState);
            }
        }

        /// <summary>
        /// 状态变更事件处理
        /// </summary>
        protected virtual void OnStateChanged(CircuitBreakerState oldState, CircuitBreakerState newState)
        {
            StateChanged?.Invoke(this, new StateChangedEventArgs(oldState, newState, _stateChangedTime));
        }

        #endregion

        #region 事件

        /// <summary>
        /// 状态变更事件
        /// </summary>
        public event EventHandler<StateChangedEventArgs> StateChanged;

        #endregion

        #region 统计方法

        /// <summary>
        /// 获取熔断器统计信息
        /// </summary>
        public CircuitBreakerStatistics GetStatistics()
        {
            lock (_lockObj)
            {
                return new CircuitBreakerStatistics
                {
                    CurrentState = _state,
                    FailureCount = _failureCount,
                    SuccessCount = _successCount,
                    LastFailureTime = _lastFailureTime,
                    StateChangedTime = _stateChangedTime,
                    HalfOpenAttempts = _halfOpenAttempts,
                    IsHealthy = _state == CircuitBreakerState.Closed,
                    TimeInCurrentState = DateTime.UtcNow - _stateChangedTime
                };
            }
        }

        #endregion
    }

    #region 辅助类和异常定义

    /// <summary>
    /// 熔断器统计信息
    /// </summary>
    public class CircuitBreakerStatistics
    {
        public CircuitBreaker.CircuitBreakerState CurrentState { get; set; }
        public int FailureCount { get; set; }
        public int SuccessCount { get; set; }
        public DateTime LastFailureTime { get; set; }
        public DateTime StateChangedTime { get; set; }
        public int HalfOpenAttempts { get; set; }
        public bool IsHealthy { get; set; }
        public TimeSpan TimeInCurrentState { get; set; }
        
        public override string ToString()
        {
            return $"状态: {CurrentState}, 失败: {FailureCount}, 成功: {SuccessCount}, " +
                   $"健康: {IsHealthy}, 当前状态时长: {TimeInCurrentState.TotalSeconds:F1}秒";
        }
    }

    /// <summary>
    /// 状态变更事件参数
    /// </summary>
    public class StateChangedEventArgs : EventArgs
    {
        public CircuitBreaker.CircuitBreakerState OldState { get; }
        public CircuitBreaker.CircuitBreakerState NewState { get; }
        public DateTime ChangedTime { get; }
        
        public StateChangedEventArgs(
            CircuitBreaker.CircuitBreakerState oldState,
            CircuitBreaker.CircuitBreakerState newState,
            DateTime changedTime)
        {
            OldState = oldState;
            NewState = newState;
            ChangedTime = changedTime;
        }
    }

    /// <summary>
    /// 熔断器开启异常
    /// </summary>
    public class CircuitBreakerOpenException : Exception
    {
        public CircuitBreakerOpenException(string message) : base(message) { }
        public CircuitBreakerOpenException(string message, Exception innerException) 
            : base(message, innerException) { }
    }

    /// <summary>
    /// 熔断器执行异常
    /// </summary>
    public class CircuitBreakerExecutionException : Exception
    {
        public CircuitBreakerExecutionException(string message) : base(message) { }
        public CircuitBreakerExecutionException(string message, Exception innerException) 
            : base(message, innerException) { }
    }

    #endregion
}